#include "header.h"

extern jpeg_header jpeg_header_info;
extern int pixels_move_per_block;
extern unsigned long dl;
extern int Tv,N;
extern uint8_t *plane_background;
extern short *M,*V,*delta;
extern int update_background;
extern int num_blocks;

void block_PIXEL_MAX(int stt_block, uint8_t* plane, int width, int block_per_width){
     unsigned long start_point=(stt_block/block_per_width)*BLOCK_SIZE*BLOCK_SIZE*block_per_width + (stt_block%block_per_width)*BLOCK_SIZE;     
     int i,j;
     unsigned long location;
     for(i=0;i<BLOCK_SIZE;i++)
       for(j=0;j<BLOCK_SIZE;j++){
           location=start_point+i*width+j;
           plane[location]=PIXEL_MAX;
       }
}
void block(int stt_block,int frame_count,int pow2,uint8_t* plane, uint8_t* plane_out, int *num_blocks_move, int vitri_block_move[]){

     int width=jpeg_header_info.width;
     int block_per_width=width/BLOCK_SIZE; 
     unsigned long start_point=(stt_block/block_per_width)*BLOCK_SIZE*BLOCK_SIZE*block_per_width + (stt_block%block_per_width)*BLOCK_SIZE; 
     int i,j,location,temp;
     int num_pixels_move=0;
     for(i=0;i<BLOCK_SIZE;i++)
       for(j=0;j<BLOCK_SIZE;j++){
           //CHIA BLOCK
           location=start_point+i*width+j;
           //ANALYSIS PIXEL
           if(V[location]>256/pow2){
               
               if(M[location] < plane[location]) M[location]=M[location]+1;
	       if(M[location] > plane[location]) M[location]=M[location]-1;
           }   
	   delta[location]=abs(M[location] - plane[location]);
           if((frame_count+1)% Tv==0){
	        if(V[location] <N*delta[location]) V[location] = V[location]+1;
		if (V[location]>N*delta[location]) V[location] = V[location]-1;
               temp= V[location] < PIXEL_MAX ? V[location]:PIXEL_MAX;
               V[location]= temp > PIXEL_MIN ? temp:PIXEL_MIN;
            }
                
            if( delta[location]>=V[location]) 
                num_pixels_move++;
           
       }
     if(num_pixels_move < pixels_move_per_block){
           for(i=0;i<BLOCK_SIZE;i++)
              for(j=0;j<BLOCK_SIZE;j++){
                    location =start_point+ i*width+j;
                    plane_out[location]=PIXEL_MAX;
              }
     }
     else{
           for(i=0;i<BLOCK_SIZE;i++)
              for(j=0;j<BLOCK_SIZE;j++){
                    location =start_point+ i*width+j;
                    plane_out[location]=plane[location];
                    //Luu stt_block detected motion.                    
                    vitri_block_move[*num_blocks_move]=stt_block;            
              }
           *num_blocks_move=*num_blocks_move+1;
     }
        
}

void zipfian(uint8_t* plane, int frame_count, uint8_t plane_out[]){

    int vitri_block_move[num_blocks];
    int num_blocks_move=0; 
    unsigned long local;
    int block_per_width=jpeg_header_info.width/BLOCK_SIZE; 
    unsigned long width =jpeg_header_info.width;
    if(frame_count%update_background==0){
       for(local=0;local<dl;local++){
	   delta[local]=V[local]=0;
           M[local]=plane_out[local]=plane_background[local]=plane[local];
       }
    }else{  
       int pow2=1,i,j; 
       int rank=(frame_count % update_background +1) % 256;
       do
          pow2=2*pow2;
       while(rank % pow2==0 && pow2<256);
       int stt_block=0;

       while(stt_block<num_blocks){
          block(stt_block,frame_count % update_background,pow2,plane,plane_out,&num_blocks_move,vitri_block_move);
          stt_block++;
       }
       for(i=0;i<num_blocks_move;i++){
            j=0;
            while((vitri_block_move[j]-vitri_block_move[i]) <= (block_per_width+1) && j<num_blocks_move){
                 int temp =vitri_block_move[j]-vitri_block_move[i];
                 int temp2=abs(temp);
                 j++;
                 int a=vitri_block_move[i]%block_per_width;
                 if(a ==0 && (temp==1|| temp2==block_per_width ||temp==(block_per_width+1) || temp==-(block_per_width-1)))
                     goto ra;
                 if(a==(block_per_width-1) && (temp==-1 || temp2==block_per_width ||temp ==(block_per_width-1) || temp==-(block_per_width+1)))
                     goto ra;
                 if(a!=0 && a !=(block_per_width-1) &&(temp2==1|| temp2==block_per_width ||temp2 ==(block_per_width-1)||temp2==(block_per_width+1)))
                     goto ra;                  
            }
            block_PIXEL_MAX(vitri_block_move[i],plane_out,width,block_per_width);
            ra: j=0;
            
       }
       
    }
}
